
#include <jni.h>
#include <android/log.h>
#include "root.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <malloc.h>

#define TAG "bili-rgun"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)

jobject Java_tv_danmaku_bili_utils_RailgunHelper_shoot(JNIEnv *env, jclass clz) {
    root_ctx ctx;
    int rc, status;
    pid_t pid;
    int fd[2];
    int png_size, png_offs;
    char *png_data, *tmp;
    jobject png;

    rc = pipe(fd);
    if (rc < 0)
        return 0;
    pid = fork();
    if (pid > 0) {
        png_size = 0;
        png_offs = 0;
        png_data = 0;
        for (;;) {
            if (png_size == png_offs) {
                png_size = png_size ? png_size * 2 : 128 * 1024;
                tmp = realloc(png_data, png_size);
                if (!tmp) {
                    if (png_data) {
                        free(png_data); png_data = 0;
                        break;
                    }
                }
                png_data = tmp;
            }
            LOGD("p read");
            rc = read(fd[0], png_data + png_offs, png_size - png_offs);
            if (rc < 0) {
                if (errno == -EINTR)
                    continue;
                free(png_data); png_data = 0;
                break;
            }
            if (rc == 0)
                break;
            png_offs += rc;
        }
        LOGD("p read end");
        close(fd[0]); close(fd[1]);
        rc = waitpid(pid, &status, 0);
        if (rc || !WIFEXITED(status) || WEXITSTATUS(status)) {
            if (png_data) {
                free(png_data); png_data = 0;
            }
            return 0;
        }
        if (!png_data || !png_offs)
            return 0;
        png = (*env)->NewByteArray(env, png_offs);
        if (!png) {
            free(png_data); png_data = 0;
            return 0;
        }
        (*env)->SetByteArrayRegion(env, png, 0, png_offs, png_data);
        free(png_data); png_data = 0;
        return png;
    } else if (pid == 0) {
        char *args[] = {"/system/bin/screencap", "-p", 0}; 
        rc = root_init(&ctx);
        if (rc < 0)
            exit(1);
        rc = root_321(&ctx);
        root_free(&ctx);
        if (rc)
            exit(1);
        LOGD("c root GD");
        // redirect stdout
        dup2(fd[1], 1);
        LOGD("c exec");
        execvp(args[0], args);
        LOGD("c NG");
        // should not be here
        exit(1);
    } else {
        close(fd[0]); close(fd[1]);
        return 0;
    }

    return 0;
}

